package com.yhq.basic.jvm.dataarea;

import com.yhq.basic.jvm.dataarea.po.User;
import lombok.SneakyThrows;

/**
 * 测试对象内存分配
 * 1.根据逃逸分析，判断对象是否能在栈上分配，若栈上没有连续的空间，则可以使用标量替换创建对象
 *  理解：1）标量替换：确定该对象没有逃逸，并且对象可以被进一步分解时，JVM不会创建该对象，
 *      而是将该对象成员变量分解若干个被该方法使用的成员变量所代替，这些代替的成员变量在栈帧或寄存器上分配空间，
 *      因此不会出现没有一块连续的大空间导致对象内存不够分配。
 *      2) 标量：是不可被分解的量，比如Java的基本数据类型；
 *      3）聚合量：可被分解为多个标量，比如Java中的对象；
 * 2.
 *
 * @author hqyin
 * @date 2024/8/8 2:21 PM
 */
public class Demo5StackObj {
    public static void main(String[] args) {
        //测试栈上分配
        //-XX:+DoEscapeAnalysis 开启逃逸分析参数
        //-XX:+EliminateAllocations  开启标量替换参数
        //-Xmx15m -Xms15m
//        test_stackAllocationObj();
        int sum = (int)Math.pow(2,7) + (int)Math.pow(2,6) + (int)Math.pow(2,5) + (int)Math.pow(2,4) + (int)Math.pow(2,3) + (int)Math.pow(2,2) + (int)Math.pow(2,1)+1;
        System.out.println(sum);
    }

    /**
     * 场景一：默认开启逃逸分析，默认开启标量替换 设置堆初始化大小15m,堆最大15m
     * -Xmx15m -Xms15m -XX:+PrintGC
     * 场景二：关闭逃逸分析
     * -Xmx15m -Xms15m -XX:+PrintGC -XX:-DoEscapeAnalysis
     * 场景三：关闭标量替换
     * -Xmx15m -Xms15m -XX:+PrintGC -XX:+DoEscapeAnalysis -XX:-EliminateAllocations
     *
     * 总结：
     */
    @SneakyThrows
    private static void test_stackAllocationObj() {
        long start = System.currentTimeMillis();
        User user = null;
        for (int i = 0; i < 1000000000; i++) {
            user = user_demo1();
            user.id=i;
//            user_demo2();
        }
        long end = System.currentTimeMillis();
        System.out.println("耗时："+(end-start));
    }

    public static User user_demo1(){
        User user = new User();
        user.id = 1;
        user.name="张三";
        return user;
    }

    public static void user_demo2(){
        User user = new User();
        user.id = 2;
        user.name="李四";
    }
}
